<?php

namespace App\Package\Attendance;

use App\Models\Attendance;
use Illuminate\Support\Collection;

/**
 * 考勤原始数据校验逻辑
 *
 * Date: 30/04/2018
 * @author George
 * @package App\Package\Attendance
 */
class Examine
{
	/**
	 * 临时存储
	 *
	 * Date: 30/04/2018
	 * @author George
	 */
	protected $attendances;

	/**
	 * Examine constructor.
	 * @param Collection $attendances
	 */
	public function __construct(Collection $attendances)
	{
		$this->attendances = $attendances;
	}

	public function result()
	{
		$this->attendances->map(function ($attendance) {
			$this->time($attendance);
		});
	}

	/**
	 * 计算考勤时间
	 *
	 * Date: 30/04/2018
	 * @author George
	 * @param Attendance $attendance
	 * @return Attendance
	 * @throws \Throwable
	 */
	protected function time(Attendance $attendance)
	{
		$delayed = config('attendance.delayed') * 60;
		$start = strtotime($attendance->schedule->start_timestamp);
		$end = strtotime($attendance->schedule->end_timestamp);

		if (! $attendance->checkin_time) {
			$attendance->checkin_status = config('attendance.status.nsignin');
		} else {
			$checkin = strtotime($attendance->checkin_time);
			// 当签到时间减去允许迟到时间大于考勤开始时间，则记为迟到
			if ($start < ($checkin - $delayed)) {
				$attendance->checkin_status = config('attendance.status.tardy');
			}
		}

		if (! $attendance->checkout_time) {
			$attendance->checkout_status = config('attendance.status.nsignout');
		} else {
			$checkout = strtotime($attendance->checkout_time);
			// 当签退时间小于考勤结束时间是，则记为早退
			if ($end > $checkout) {
				$attendance->checkout_status = config('attendance.status.early');
			}
		}

		$attendance->checkin_status = $attendance->checkin_status ?? config('attendance.status.normal');
		$attendance->checkout_status = $attendance->checkout_status ?? config('attendance.status.normal');
		$attendance->saveOrFail();
		return $attendance;
	}

	/**
	 * 判断考勤范围是否在范围内
	 *
	 * Date: 30/04/2018
	 * @author George
	 * @param Attendance $attendance
	 * @return \Illuminate\Config\Repository|mixed
	 */
	protected function scope(Attendance $attendance)
	{
		$project = $attendance->project;
		$range = $this->calculationRange($project->longitude, $project->latitude, $project->radius);
		// 判断签到经度是否在范围内
		if ($attendance->checkin_longitude > $range['longitude']['start'] && $attendance->checkin_longitude < $range['longitude']['end']) {
			// 判断签到纬度是否在范围内
			if ($attendance->checkin_latitude > $range['latitude']['start'] && $attendance->checkin_latitude < $range['latitude']['end']) {
				// 判断签退经度是否在范围内
				if ($attendance->checkout_longitude > $range['longitude']['start'] && $attendance->checkout_longitude < $range['longitude']['end']) {
					// 判断签退纬度是否在范围内
					if ($attendance->checkout_latitude > $range['latitude']['start'] && $attendance->checkout_latitude < $range['latitude']['end']) {
						return config('attendance.status.normal');
					}
				}
			}
		}

		return config('attendance.status.beyond');
	}

	private function calculationRange($longitude, $latitude, $distance = 0.5, $radius = 6371)
	{
		$dlongitude = 2 * asin(sin($distance / (2 * $radius)) / cos(deg2rad($latitude)));
		$dlongitude = rad2deg($dlongitude);
		$dlatitude = $distance / $radius;
		$dlatitude = rad2deg($dlatitude);

		return [
			'longitude' => [
				'start' => $longitude - $dlongitude,
				'end' => $longitude + $dlongitude
			],
			'latitude' => [
				'start' => $latitude - $dlatitude,
				'end' => $latitude + $dlatitude
			],
		];
	}
}
